/**
 * Context 上下文，对标 Vue 中依赖注入（provide inject）
 *
 *    为什么有 Context 这个东西？
 *       当组件层级嵌套非常深的时候，要实现数据的传递需要一层一层通过prop往下传递，非常麻烦。于是提供了 Context 。
 *
 *    类组件如何使用
 *      一：
 *        1. 需要通过 React.createContext(defaultValue) 创建一个 context 对象
 *              该方法可以传递一个默认的 value 的值
 *        2. 要使用的组件就直接引入该 context 对象，且设置到类的 contextType 属性上。
 *        3. 该组件就可以通过 this.context 获取到 context 对象的内容了。
 *
 *      二：
 *        上面的一套代码中，设置了 defaultValue ，但是没法修改它，为了实现可以修改的操作。需要使用 context的 Provider 组件，包裹在需要使用的组件外面。
 *
 *        1. 需要通过 createContext() 创建一个 context 对象
 *        2. 将 context 对象的 Provider 组件用上, 且设置 value 值，value 值可以为一个 state 数据
 *        3. 只要是属于这个 Provider 组件的 子孙组件，都可以 获取到该 Provider 上提供的 value 值。
 *            且当该 Provider 的 value 值发生变化时，组件可以得到最新的一份值。
 *
 *      三：
 *        结合第二种来说，Provider 有一个配套的 Consumer 组件，在后代组件中可以通过 Consumer 来获取 Provider 提供下来的值，也就是说不需要设置 static contextType 了。
 */

import React from "react";

// 引入创建好的 context
import c1Context from "./contexts/c-1";

import C2Context from "./contexts/c-2";

console.log("C2Context", C2Context);

class Button extends React.Component {
  // static contextType = C2Context;

  render() {
    return (
      <div>
        {/* 
          Consumer , 接受一个 函数类型的 children prop
              1. 函数会自动调用，且会接收到一个参数，参数值就是配套的 Provider 的提供值。

        */}
        <C2Context.Consumer>
          {(value) => {
            return <button>Button - {value}</button>;
          }}
        </C2Context.Consumer>
      </div>
    );
  }
}

class Hello extends React.Component {
  static contextType = C2Context;

  render() {
    return (
      <div>
        <h4>Hello - {this.context}</h4>

        <hr />

        <Button />
      </div>
    );
  }
}

class App extends React.Component {
  state = {
    name: "张三",
  };

  render() {
    return (
      <C2Context.Provider value={this.state.name}>
        <h1>App</h1>
        <button
          onClick={() =>
            this.setState((prevState) => ({
              name: prevState.name + "~",
            }))
          }
        >
          修改我的 name，我后代通过 Context 获取到的值都会跟着变
        </button>
        <hr />
        <Hello />
      </C2Context.Provider>
    );
  }
}

// class App extends React.Component {
//   // 将某个 context 对象，赋值给 组件的 contextType 静态属性，于是该组件 this.context 的值 就是这个 context 对象的 value 值
//   static contextType = c1Context;

//   render() {
//     console.log(this);
//     return (
//       <div>
//         <h1>App</h1>
//         <p>c1Context: {this.context}</p>
//       </div>
//     );
//   }
// }
// App.contextType = c1Context;

export default App;
